﻿using System;
using System.ComponentModel;
using System.Windows;
using System.Windows.Input;

using Microsoft.Practices.Composite.Presentation.Commands;
using Microsoft.Practices.Unity;

using Supremacy.Annotations;
using Supremacy.Client.Commands;
using Supremacy.Diplomacy;
using Supremacy.Game;
using Supremacy.Universe;

namespace Supremacy.Client.Views
{
    public partial class GalaxyGridView : IWeakEventListener
    {
        private readonly IUnityContainer _container;
        private readonly IClientContext _clientContext;
        private readonly INavigationCommandsProxy _navigationCommands;
        private readonly DelegateCommand<object> _revealMapCommand;

        #region Constructors and Finalizers
        public GalaxyGridView([NotNull] IUnityContainer container)
        {
            if (container == null)
                throw new ArgumentNullException("container");

            _container = container;
            _clientContext = _container.Resolve<IClientContext>();
            _navigationCommands = _container.Resolve<INavigationCommandsProxy>();

            InitializeComponent();

            this.Loaded += delegate
                           {
                               this.GalaxyGrid.Update();
                               this.GalaxyGrid.SelectedSector = _clientContext.LocalPlayerEmpire.HomeColony.Sector;
                               this.GalaxyGrid.CenterOnSelectedSector();
                           };
            this.Unloaded += OnUnloaded;

            this.GalaxyGrid.SectorDoubleClicked += OnSectorDoubleClicked;

            PropertyChangedEventManager.AddListener(_clientContext, this, "LocalPlayerEmpire");
            
            _revealMapCommand = new DelegateCommand<object>(ExecuteRevealMapCommand);

            DebugCommands.RevealMap.RegisterCommand(_revealMapCommand);
        }

        private void OnUnloaded(object sender, RoutedEventArgs args)
        {
            this.GalaxyGrid.SectorDoubleClicked -= OnSectorDoubleClicked;
            this.Content = null;
            this.GalaxyGrid = null;
            DebugCommands.RevealMap.UnregisterCommand(_revealMapCommand);
        }

        private void OnLocalPlayerEmpireChanged()
        {
            if (!_clientContext.IsGameInPlay || _clientContext.IsGameEnding)
                return;

            var localPlayerEmpire = _clientContext.LocalPlayerEmpire;
            if (localPlayerEmpire == null)
                return;
        }

        private void OnSectorDoubleClicked(Sector sector)
        {
            if ((sector == null) || (sector.System == null))
                return;

            var colony = sector.System.Colony;
            if (colony == null)
                return;

            _navigationCommands.ActivateScreen.Execute(StandardGameScreens.ColonyScreen);
        }

        private void ExecuteRevealMapCommand(object t)
        {
            var map = _clientContext.CurrentGame.Universe.Map;
            var playerCiv = _clientContext.LocalPlayer.Empire;
            var mapData = _clientContext.LocalPlayerEmpire.MapData;
            for (int x = 0; x < map.Width; x++)
            {
                for (int y = 0; y < map.Height; y++)
                {
                    mapData.SetExplored(new MapLocation(x, y), true);
                }
            }
            foreach (var civ in GameContext.Current.Civilizations)
            {
                if (civ == playerCiv)
                    continue;
                if (_clientContext.CurrentGame.DiplomacyStatus[playerCiv, civ] == DiplomacyStatus.NoContact)
                    _clientContext.CurrentGame.DiplomacyStatus[playerCiv, civ] = DiplomacyStatus.Neutral;
            }
            this.GalaxyGrid.Update();
        }
        #endregion

        public bool ReceiveWeakEvent(Type managerType, object sender, EventArgs e)
        {
            var clientContext = sender as IClientContext;
            
            if (clientContext == null)
                return false;

            var propertyChangedEventArgs = e as PropertyChangedEventArgs;
            if (propertyChangedEventArgs == null)
                return false;

            switch (propertyChangedEventArgs.PropertyName)
            {
                case "LocalPlayerEmpire":
                    OnLocalPlayerEmpireChanged();
                    break;
            }

            return true;
        }
    }
}